package Modele;

import java.util.ArrayList;

/**
 * Classe permettant d'effectuer les contrôles pour se deplacer
 * @author El Meknassi Hamza (10806466) - Migeon Cyril (11007322)
 */
public class ControleDeplacement {
    
    /**
     * Constructeur de Deplacement
     */
    public ControleDeplacement(){}
    
    /**
     * Permet de récupérer une pièce
     * @param maCase contient la case avec la pièce
     * @return piece
     */
    public Piece recupererPiece(Case maCase){        
        return maCase.getPiece();
    }
    
    /**
     * Permet de savoir si la pièce sur la case est blanche ou non
     * @param maCase
     * @return true si la pièce sur la case est blanche, false sinon
     */
    public boolean couleurBlanche(Case maCase){
        /* On récupère la pièce associé à la case */
        Piece maPiece = maCase.getPiece();
        char couleurPiece = maPiece.getCouleur();
        
        if(couleurPiece == 'b')
            return true;
        else
            return false;
    }
    
    /**
     * Retourne true si couleur='b' (blanche)
     * @param couleur
     * @return true si la couleur est blanche, false sinon
     */
    public boolean couleurBlanche(char couleur){
        if(couleur == 'b')
            return true;
        else
            return false;
    }

    /**
     * Permet de savoir si le joueur est blanc ou non
     * @param monJoueur
     * @return true si le joueur est blanc, false sinon
     */
    public boolean couleurBlanche(Joueur monJoueur){
        char couleurPiece = monJoueur.getCouleur();
        
        if(couleurPiece == 'b')
            return true;
        else
            return false;
    }
    
    /**
     * Permet de savoir si la pièce sur la case est noire ou non
     * @param maCase
     * @return true si la pièce sur la case est noire, false sinon
     */
    public boolean couleurNoire(Case maCase){
        /* On récupère la pièce associé à la case */
        Piece maPiece = maCase.getPiece();
        char couleurPiece = maPiece.getCouleur();
        
        if(couleurPiece == 'n')
            return true;
        else
            return false;
    }
    
    /**
     * Retourne true si couleur='n' (noire)
     * @param couleur
     * @return true si la couleur est noire, false sinon
     */
    public boolean couleurNoire(char couleur){
        if(couleur == 'n')
            return true;
        else
            return false;
    }
    
    /**
     * Permet de savoir si le joueur est noir ou non
     * @param monJoueur
     * @return true si le joueur est noir, false sinon
     */
    public boolean couleurNoire(Joueur monJoueur){
        char couleurPiece = monJoueur.getCouleur();
        
        if(couleurPiece == 'n')
            return true;
        else
            return false;
    }
    
    /**
     * Compare si les pièces sur les 2 cases sont de la même couleur
     * @param case1
     * @param case2
     * @return true si les pièces sur les cases sont de même couleur, false sinon
     */
    public boolean comparerCouleurCases(Case case1, Case case2){
        if((couleurBlanche(case1) && couleurBlanche(case2)) || (couleurNoire(case1) && couleurNoire(case2)))
            return true;
        else
            return false;
    }
    
    /**
     * 
     * @param couleur
     * @param case2
     * @return 
     */
    public boolean comparerCouleurCases(char couleur, Case case2){
        if((couleurBlanche(couleur) && couleurBlanche(case2)) || (couleurNoire(couleur) && couleurNoire(case2)))
            return true;
        else
            return false;
    }
    
    /**
     * Permet de savoir si une pièce est située sur une case
     * @param maCase
     * @return true si une pièce est située sur la case, false sinon
     */
    public boolean pieceDisponibleSurCase(Case maCase){
        int etat = maCase.getEtat();
        if(etat == 1)
            return true;
        else
            return false;
    }
    
    /**
     * Permet de savoir si le joueur a le droit de jouer la pièce sur une case
     * @param maCase soit la case qui contient la pièce
     * @param monJoueur soit le joueur
     * @return true si le joueur peut joueur la pièce sur la case, false sinon.
     */
    public boolean JoueurPeutJouerPiece(Case maCase, Joueur monJoueur){
        if((couleurBlanche(maCase) && couleurBlanche(monJoueur)) || (couleurNoire(maCase) && couleurNoire(monJoueur)))
            return true;
        else
            return false;
    }
    
    /**
     * Verifie si un déplacement simple (sans prise de pièce) est possible
     * @param caseDepart
     * @param caseCible
     * @return true si le déplacement est possible, false sinon
     */
    private boolean deplacementSimple(Case caseDepart, Case caseCible){
        boolean booleen = true;
        
        boolean pieceBlanche = this.couleurBlanche(caseDepart);
        boolean matchArrayList = false;
        
        Piece piece = caseDepart.getPiece();
        
        ArrayList<Position> casesCiblesPossibles = new ArrayList<Position>();
        
        /* On récupère les coordonnées de la case départ */
        int xCaseDepart = caseDepart.getPositionX();
        int yCaseDepart = caseDepart.getPositionY();
        
        /* On récupère les coordonnées de la case cible */
        int xCaseCible = caseCible.getPositionX();
        int yCaseCible = caseCible.getPositionY();
        
        /* On définit les cases cibles possibles */
        if(!pieceBlanche)
        {
            if(xCaseDepart>0 && yCaseDepart < 9)
                casesCiblesPossibles.add(new Position(xCaseDepart-1, yCaseDepart+1));
            if(xCaseDepart<9 && yCaseDepart < 9)
                casesCiblesPossibles.add(new Position(xCaseDepart+1, yCaseDepart+1));
            
            if(piece instanceof Dame)
            {
                if(xCaseDepart>0 && yCaseDepart > 0)
                    casesCiblesPossibles.add(new Position(xCaseDepart-1, yCaseDepart-1));
                if(xCaseDepart<9 && yCaseDepart > 0)
                    casesCiblesPossibles.add(new Position(xCaseDepart+1, yCaseDepart-1));
            }
        }
        else
        {
            if(xCaseDepart>0)
                casesCiblesPossibles.add(new Position(xCaseDepart-1, yCaseDepart-1));
            if(xCaseDepart<9)
                casesCiblesPossibles.add(new Position(xCaseDepart+1, yCaseDepart-1));
            
            if(piece instanceof Dame)
            {
                if(xCaseDepart>0 && yCaseDepart < 9)
                    casesCiblesPossibles.add(new Position(xCaseDepart-1, yCaseDepart+1));
                if(xCaseDepart < 9 && yCaseDepart < 9)
                    casesCiblesPossibles.add(new Position(xCaseDepart+1, yCaseDepart+1));
            }
        }
        
        /* On teste si la case est inoccupée */
        if(pieceDisponibleSurCase(caseCible))
            booleen = false;
        
        /* On teste si la position de la case cible est une position possible */
        for(Position positionTest : casesCiblesPossibles)
        {
            if(positionTest.comparePosition(xCaseCible, yCaseCible))
                matchArrayList = true;
        }
        
        if(!matchArrayList)
            booleen = false;
            
        return booleen;
    }
    
    /**
     * Verifie si un déplacement avec prise est possible
     * @param caseDepart
     * @param caseInter
     * @param caseCible
     * @param couleurCaseDepart 
     * @return true si le déplacement est possible, false sinon
     */
    private boolean deplacementPrise(Case caseDepart, Case caseInter, Case caseCible, char couleurCaseDepart){
        boolean booleen = true;
        
        boolean matchArrayList = false;
        
        ArrayList<Position> casesCiblesPossibles = new ArrayList<Position>();
        
        /* On récupère les coordonnées de la case départ */
        int xCaseDepart = caseDepart.getPositionX();
        int yCaseDepart = caseDepart.getPositionY();
        
        /* On récupère les coordonnées de la case cible */
        int xCaseCible = caseCible.getPositionX();
        int yCaseCible = caseCible.getPositionY();
        
        /* On fait les tests pour voir quels cases cibles sont possible à atteindre */
        if(xCaseDepart > 1 && yCaseDepart < 8)
            casesCiblesPossibles.add(new Position(xCaseDepart-2, yCaseDepart+2));
        
        if(xCaseDepart > 1 && yCaseDepart > 1)
            casesCiblesPossibles.add(new Position(xCaseDepart-2, yCaseDepart-2));
        
        if(xCaseDepart < 8 && yCaseDepart < 8)
            casesCiblesPossibles.add(new Position(xCaseDepart+2, yCaseDepart+2));
        
        if(xCaseDepart < 8 && yCaseDepart > 1)
            casesCiblesPossibles.add(new Position(xCaseDepart+2, yCaseDepart-2));
        
        /* On teste si la case est inoccupée */
        if(pieceDisponibleSurCase(caseCible))
            booleen = false;
        
        /* On teste si la position de la case cible est une position possible */
        for(Position positionTest : casesCiblesPossibles)
        {
            if(positionTest.comparePosition(xCaseCible, yCaseCible))
                matchArrayList = true;
        }
        
        /* On vérifie qu'une pièce est disponible sur la case intermédiaire */
        if(!pieceDisponibleSurCase(caseInter))
            booleen = false;        
        
        if(booleen)
        {
            if(this.comparerCouleurCases(couleurCaseDepart, caseInter))
                booleen = false;
        }
        
        return booleen;
    }
    
    /**
     * Verifie si le déplacement est possible
     * @param caseDepart
     * @param caseCible
     * @return true si le déplacement est possible, false sinon
     */
    public boolean deplacementPossible(Case caseDepart, Case caseCible){
        if(deplacementSimple(caseDepart, caseCible))
            return true;
        else
            return false;
    }
    
    /**
     * Verifie si le déplacement est possible
     * @param caseDepart
     * @param caseInter
     * @param caseCible
     * @param couleurCaseDepart 
     * @return true si le déplacement est possible, false sinon
     */
    public boolean deplacementPossible(Case caseDepart, Case caseInter, Case caseCible, char couleurCaseDepart){
        if(deplacementPrise(caseDepart, caseInter, caseCible, couleurCaseDepart))
            return true;
        else
            return false;
    }
}
